package main.java.service;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import main.java.DAO.INewsDAO;
import main.java.constant.StateEnum;
import main.java.controller.NewsController.NewsCreateFormTransmitter;
import main.java.model.AttachmentModel;
import main.java.model.NewsInfoModel;
import main.java.model.UserInfoBasicModel;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import util.judking.DbHelper;

@Service("newsService")
public class NewsService {
	@Autowired
	@Qualifier("INewsDAO")
	private INewsDAO newsDAO;
	@Autowired
	@Qualifier("resourceService")
	ResourceService resourceService;
	@Autowired
	@Qualifier("userService")
	UserService userService;
	@Autowired
	@Qualifier("transactionManager")
	private DataSourceTransactionManager dataSourceTransactionManager;
	
	// --create post
	public StateEnum create(NewsCreateFormTransmitter newsCreateFormTransmitter, String servletPath) throws IOException			{
		//------------- write newsPage, newsSilder, newsAttachment -------------
		File newsPageFile = null;
		File newsSliderFile = null;
		List<File> newsAttachmentFiles = new ArrayList<File>();
		String newsPageDirectory = resourceService.getCurrentWebappRootPath()+servletPath;
		try {
			String newsPageName = createNewsPageName("jsp");
			String newsSliderName = createNewsSliderName(newsPageName, newsCreateFormTransmitter.getSlider().getFileItem().getName());
			
			newsPageFile = resourceService.genFile(newsPageName, newsPageDirectory);
			resourceService.writeToFile(newsPageFile, newsCreateFormTransmitter.getContent().getBytes(), false);
			
			newsSliderFile = resourceService.genFile(newsSliderName, newsPageDirectory, "/slider");
			resourceService.writeToFile(newsSliderFile, newsCreateFormTransmitter.getSlider().getFileItem().get(), false);
			
			for(int i = 0; i < newsCreateFormTransmitter.getFiles().size(); ++i)		{
				String newsAttachmentName = createNewsAttachmentName(newsPageName, newsCreateFormTransmitter.getFiles().get(i).getFileItem().getName());
				File newsAttachmentFile = resourceService.genFile(newsAttachmentName, newsPageDirectory, "/upload");
				resourceService.writeToFile(newsAttachmentFile, newsCreateFormTransmitter.getFiles().get(i).getFileItem().get(), false);
				newsAttachmentFiles.add(newsAttachmentFile);
			}
		} catch (IOException e) {
			//�ع�IO����
			newsCreateRollBackIO(newsPageFile, newsSliderFile, newsAttachmentFiles);
			throw e;
		}

		//------------- fully populate the newsInfoModel & attachmentModel -------------
		newsCreateFullyPopulate(newsCreateFormTransmitter, newsPageFile, newsSliderFile, newsAttachmentFiles);
		
		//------------- begin a transaction for registering to DB -------------
		NewsInfoModel newsInfoModel = newsCreateFormTransmitter.getNewsInfoModel();
		TransactionStatus status = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
		try	{
			//insert news info into news_info table
			DbHelper.assertGtZero(newsDAO.insertNewsInfo(newsInfoModel));
			
			//insert each attachment into attachment table
			for(AttachmentModel attachmentModel : newsInfoModel.getAttachment_model_list())		{
				//set news_info_id into attachmentModel
				attachmentModel.setNews_info_id(newsInfoModel.getNews_info_id());
				DbHelper.assertGtZero(newsDAO.insertAttachment(attachmentModel));
			}
			
			dataSourceTransactionManager.commit(status);
			return StateEnum.SUCCESS;
		}catch(RuntimeException e)		{
			dataSourceTransactionManager.rollback(status);
			throw e;
		}
	}
	
	/**
	 * create name for the newly-created news page. 
	 * ( due to the current date and time )
	 * @param suffix file suffix
	 * @return file name
	 */
	private String createNewsPageName(String suffix)		{
		Date date = new Date();
		DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
		return "news_"+dateFormat.format(date)+"."+suffix;
	}
	
	/**
	 * create name for the slider binding to the news page
	 * @param newsPageName
	 * @param sliderName the name for the uploaded slider picture
	 * @return
	 */
	private String createNewsSliderName(String newsPageName, String sliderName)			{
		StringBuilder newsSliderName = new StringBuilder();
		newsSliderName.append(resourceService.getFileNamePrefix(newsPageName));
		newsSliderName.append("_slider.");
		newsSliderName.append(resourceService.getFileNameSuffix(sliderName));
		
		return newsSliderName.toString();
	}
	
	/**
	 * create name for the attachment binding to the news page
	 * @param newsPageName
	 * @param attachmentName
	 * @return
	 */
	private String createNewsAttachmentName(String newsPageName, String attachmentName)		{
		StringBuilder newsAttachmentName = new StringBuilder();
		newsAttachmentName.append(resourceService.getFileNamePrefix(newsPageName));
		newsAttachmentName.append("_");
		newsAttachmentName.append(attachmentName);
		
		return newsAttachmentName.toString();
	}

	/**
	 * ��news create��IO�����Ļع�
	 * @param newsPageFile
	 * @param newsSliderFile
	 * @param newsAttachmentFiles
	 */
	private void newsCreateRollBackIO(File newsPageFile, File newsSliderFile, List<File> newsAttachmentFiles)		{
		if(newsPageFile != null && newsPageFile.exists())		{
			newsPageFile.delete();
		}
		if(newsSliderFile != null && newsSliderFile.exists())	{
			newsSliderFile.delete();
		}
		for(File newsAttachmentFile : newsAttachmentFiles)		{
			if(newsAttachmentFile != null && newsAttachmentFile.exists())		{
				newsAttachmentFile.delete();
			}
		}
	}

	/**
	 * ���IO�����ͱ?�ύ��ݣ���ȫ���NewsInfoModel����
	 * �Ա����DB�����Ľ���
	 * @param newsCreateFormTransmitter
	 * @param newsPageFile
	 * @param newsSliderFile
	 * @param newsAttachmentFiles
	 */
	private void newsCreateFullyPopulate(
			NewsCreateFormTransmitter newsCreateFormTransmitter,
			File newsPageFile,
			File newsSliderFile,
			List<File> newsAttachmentFiles
			)		{
		NewsInfoModel newsInfoModel = newsCreateFormTransmitter.getNewsInfoModel();
		List<AttachmentModel> attachmentModels = newsInfoModel.getAttachment_model_list();
		
		//set author_id to NewsInfoModel
		newsInfoModel.setAuthor_id(userService.getCurrentLoginUserInfoBasicModel().getId());
		
		//set page_link & slider_link to NewsInfoModel
		newsInfoModel.setPage_link(newsPageFile.toString());
		newsInfoModel.setSlider_link(newsSliderFile.toString());
		
		//assemble AttachmentModels
		for(int i = 0; i < newsAttachmentFiles.size(); ++i)			{
			attachmentModels.add(new AttachmentModel(""+newsCreateFormTransmitter.getFiles().get(i).getFileItem().getSize(), newsAttachmentFiles.get(i).toString()));
		}
	}
}
